home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / dev / cross / avra-0.4_src.lha / avra-0.4 / parser.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-03-24  |  9.1 KB  |  362 lines

  1. /***********************************************************************
  2.  *  avra - Assembler for the Atmel AVR microcontroller series
  3.  *  Copyright (C) 1998-1999 Jon Anders Haugum
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  18.  *  Boston, MA 02111-1307, USA.
  19.  *
  20.  *
  21.  *  Author of avra can be reached at:
  22.  *     email: jonah@omegav.ntnu.no
  23.  *     www: http://www.omegav.ntnu.no/~jonah/el/avra.html
  24.  */
  25.  
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <ctype.h>
  30.  
  31. #include "misc.h"
  32. #include "avra.h"
  33.  
  34. /*
  35.  * Parses given assembler file
  36.  */
  37.  
  38. int parse_file(struct prog_info *pi, char *filename, int pass)
  39.     {
  40.     int ok = True, loopok;
  41.     struct file_info *fi;
  42.     struct include_file *include_file;
  43.  
  44.     fi = malloc(sizeof(struct file_info));
  45.     if(fi)
  46.         {
  47.         pi->fi = fi;
  48.         if(pass == PASS_1)
  49.             {
  50.             include_file = malloc(sizeof(struct include_file));
  51.             if(!include_file)
  52.                 {
  53.                 print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  54.                 free(fi);
  55.                 return(False);
  56.                 }
  57.             include_file->next = NULL;
  58.             if(pi->last_include_file)
  59.                 {
  60.                 pi->last_include_file->next = include_file;
  61.                 include_file->num = pi->last_include_file->num + 1;
  62.                 }
  63.             else
  64.                 {
  65.                 pi->first_include_file = include_file;
  66.                 include_file->num = 0;
  67.                 }
  68.             pi->last_include_file = include_file;
  69.             include_file->name = malloc(strlen(filename) + 1);
  70.             if(!include_file->name)
  71.                 {
  72.                 print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  73.                 free(fi);
  74.                 return(False);
  75.                 }
  76.             strcpy(include_file->name, filename);
  77.             }
  78.         else
  79.             {
  80.             for(include_file = pi->first_include_file; include_file; include_file = include_file->next)
  81.                 if(!strcmp(include_file->name, filename))
  82.                     break;
  83.             }
  84.         if(!include_file)
  85.             {
  86.             print_msg(pi, MSGTYPE_ERROR, "Internal assembler error");
  87.             free(fi);
  88.             return(False);
  89.             }
  90.         fi->include_file = include_file;
  91.         fi->line_number = 0;
  92.         fi->exit_file = False;
  93.         fi->fp = fopen(filename, "r");
  94.         if(fi->fp)
  95.             {
  96.             loopok = True;
  97.             while(loopok && !fi->exit_file)
  98.                 {
  99.                 if(fgets(fi->buff, LINEBUFFER_LENGTH, fi->fp))
  100.                     {
  101.                     fi->line_number++;
  102.                     pi->list_line = fi->buff;
  103.                     ok = parse_line(pi, fi->buff, pass);
  104.                     if(ok)
  105.                         {
  106.                         if((pass == PASS_2) && pi->list_line && pi->list_on)
  107.                             fprintf(pi->list_file, "         %s", pi->list_line);
  108.                         if(pi->error_count >= pi->max_errors)
  109.                             {
  110.                             print_msg(pi, MSGTYPE_MESSAGE, "Maximum error count reached. Exiting...");
  111.                             loopok = False;
  112.                             }
  113.                         }
  114.                     else
  115.                         loopok = False;
  116.                     }
  117.                 else
  118.                     {
  119.                     loopok = False;
  120.                     if(!feof(fi->fp))
  121.                         {
  122.                         ok = False;
  123.                         perror(filename);
  124.                         }
  125.                     }
  126.                 }
  127.             fclose(fi->fp);
  128.             }
  129.         else
  130.             {
  131.             ok = False;
  132.             perror(filename);
  133.             }
  134.         free(fi);
  135.         }
  136.     else
  137.         {
  138.         ok = False;
  139.         print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  140.         }
  141.     return(ok);
  142.     }
  143.  
  144.  
  145. /*
  146.  * Parses one line
  147.  */
  148.  
  149. int parse_line(struct prog_info *pi, char *line, int pass)
  150.     {
  151.     int ok, i, j, k, global_label = False;
  152.     char temp[LINEBUFFER_LENGTH];
  153.     struct label *label = NULL;
  154.     struct macro_call *macro_call;
  155.  
  156.     /* Find out if there is any relevant code on the line. If not? return */
  157.     i = 0;
  158.     while(IS_HOR_SPACE(line[i]) && !IS_END(line[i])) i++;
  159.     if(IS_END(line[i]))
  160.         return(True);
  161.  
  162.     strcpy(temp, &line[i]);
  163.  
  164.     /* Calculate any expression inside a pair of {} */
  165.     for(i = 0, j = 0; temp[j] != '\0'; i++, j++)
  166.         {
  167.         if(temp[j] == '{')
  168.             {
  169.             k = ++j;
  170.             while((temp[j] != '\0') && (temp[j] != '}')) j++;
  171.             if(IS_END(temp[j]))
  172.                 {
  173.                 print_msg(pi, MSGTYPE_ERROR, "Found no matching }");
  174.                 break;
  175.                 }
  176.             else
  177.                 {
  178.                 temp[j] = '\0';
  179.                 if(!get_expr(pi, &temp[k], &k))
  180.                     return(False);
  181.                 sprintf(&pi->fi->scratch[i], "%d", k);
  182.                 i = strlen(pi->fi->scratch) - 1;
  183.                 }
  184.             }
  185.         else
  186.             pi->fi->scratch[i] = temp[j];
  187.         }
  188.  
  189.     /* Detect the global keyword for global labels */
  190.     if(!nocase_strncmp(pi->fi->scratch, "global", 6) && IS_HOR_SPACE(pi->fi->scratch[6]))
  191.         {
  192.         global_label = True;
  193.         i = 7;
  194.         while(IS_HOR_SPACE(pi->fi->scratch[i]) && !IS_END(pi->fi->scratch[i])) i++;
  195.         if(IS_END(pi->fi->scratch[i]))
  196.             {
  197.             print_msg(pi, MSGTYPE_ERROR, "Foung no label after global keyword");
  198.             return(True);
  199.             }
  200.         strcpy(pi->fi->scratch, &pi->fi->scratch[i]);
  201.         }
  202.  
  203.     for(i = 0; IS_LABEL(pi->fi->scratch[i]) || (pi->fi->scratch[i] == ':'); i++)
  204.         if(pi->fi->scratch[i] == ':')
  205.             {
  206.             pi->fi->scratch[i] = '\0';
  207.             if(pass == PASS_1)
  208.                 {
  209.                 for(macro_call = pi->macro_call; macro_call; macro_call = macro_call->prev_on_stack)
  210.                     {
  211.                     for(label = pi->macro_call->first_label; label; label = label->next)
  212.                         {
  213.                         if(!nocase_strcmp(label->name, &pi->fi->scratch[0]))
  214.                             {
  215.                             print_msg(pi, MSGTYPE_ERROR, "Can't redefine local label %s", &pi->fi->scratch[0]);
  216.                             break;
  217.                             }
  218.                         }
  219.                     }
  220.                 for(label = pi->first_label; label; label = label->next)
  221.                     {
  222.                     if(!nocase_strcmp(label->name, &pi->fi->scratch[0]))
  223.                         {
  224.                         print_msg(pi, MSGTYPE_ERROR, "Can't redefine label %s", &pi->fi->scratch[0]);
  225.                         break;
  226.                         }
  227.                     }
  228.                 for(label = pi->first_variable; label; label = label->next)
  229.                     if(!nocase_strcmp(label->name, &pi->fi->scratch[0]))
  230.                         {
  231.                         print_msg(pi, MSGTYPE_ERROR, "%s have already been defined as a .SET variable", &pi->fi->scratch[0]);
  232.                         break;
  233.                         }
  234.                 for(label = pi->first_constant; label; label = label->next)
  235.                     if(!nocase_strcmp(label->name, &pi->fi->scratch[0]))
  236.                         {
  237.                         print_msg(pi, MSGTYPE_ERROR, "%s have already been defined as a .EQU constant", &pi->fi->scratch[0]);
  238.                         break;
  239.                         }
  240.                 label = malloc(sizeof(struct label));
  241.                 if(!label)
  242.                     {
  243.                     print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  244.                     return(False);
  245.                     }
  246.                 label->next = NULL;
  247.                 label->name = malloc(strlen(&pi->fi->scratch[0]) + 1);
  248.                 if(!label->name)
  249.                     {
  250.                     print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  251.                     return(False);
  252.                     }
  253.                 strcpy(label->name, &pi->fi->scratch[0]);
  254.                 switch(pi->segment)
  255.                     {
  256.                     case SEGMENT_CODE:
  257.                         label->value = pi->cseg_addr;
  258.                         break;
  259.                     case SEGMENT_DATA:
  260.                         label->value = pi->dseg_addr;
  261.                         break;
  262.                     case SEGMENT_EEPROM:
  263.                         label->value = pi->eseg_addr;
  264.                         break;
  265.                     }
  266.                 if(pi->macro_call && !global_label)
  267.                     {
  268.                     if(pi->macro_call->last_label)
  269.                         pi->macro_call->last_label->next = label;
  270.                     else
  271.                         pi->macro_call->first_label = label;
  272.                     pi->macro_call->last_label = label;
  273.                     }
  274.                 else
  275.                     {
  276.                     if(pi->last_label)
  277.                         pi->last_label->next = label;
  278.                     else
  279.                         pi->first_label = label;
  280.                     pi->last_label = label;
  281.                     }
  282.                 }
  283.             i++;
  284.             while(IS_HOR_SPACE(pi->fi->scratch[i]) && !IS_END(pi->fi->scratch[i])) i++;
  285.             if(IS_END(pi->fi->scratch[i]))
  286.                 {
  287.                 if((pass == PASS_2) && pi->list_on) // Diff tilpassing
  288.                     {
  289.                     fprintf(pi->list_file, "          %s", pi->list_line);
  290.                     pi->list_line = NULL;
  291.                     }
  292.                 return(True);
  293.                 }
  294.             strcpy(pi->fi->scratch, &pi->fi->scratch[i]);
  295.             break;
  296.             }
  297.  
  298.     if(pi->fi->scratch[0] == '.')
  299.         {
  300.         pi->fi->label = label;
  301.         ok = parse_directive(pi, pass);
  302.         if((pass == PASS_2) && pi->list_on && pi->list_line) // Diff tilpassing
  303.             {
  304.             fprintf(pi->list_file, "          %s", pi->list_line);
  305.             pi->list_line = NULL;
  306.             }
  307.         return(ok);
  308.         }
  309.     else
  310.         {
  311.         ok = parse_mnemonic(pi, pass);
  312.         return(ok);
  313.         }
  314.     }
  315.  
  316.  
  317. /*
  318.  * Get the next token, and terminate the last one
  319.  * Termination identifier is specified
  320.  */
  321.  
  322. char *get_next_token(char *data, int term)
  323.     {
  324.     int i = 0, j, anti_comma = False;
  325.  
  326.     switch(term)
  327.         {
  328.         case TERM_END:
  329.             while(!IS_END(data[i])) i++;
  330.             break;
  331.         case TERM_SPACE:
  332.             while(!IS_HOR_SPACE(data[i]) && !IS_END(data[i])) i++;
  333.             break;
  334.         case TERM_COMMA:
  335.             while(((data[i] != ',') || anti_comma)
  336.                   && !(((data[i] == ';') && !anti_comma) || (data[i] == 10) || (data[i] == 13)|| (data[i] == '\0')))
  337.                 {
  338.                 if((data[i] == '\'') || (data[i] == '"'))
  339.                     anti_comma = anti_comma ? False : True;
  340.                 i++;
  341.                 }
  342.             break;
  343.         case TERM_EQUAL:
  344.             while((data[i] != '=') && !IS_END(data[i])) i++;
  345.             break;
  346.         }
  347.     if(IS_END(data[i]))
  348.         {
  349.         data[i--] = '\0';
  350.         while(IS_HOR_SPACE(data[i])) data[i--] = '\0';
  351.         return(0);
  352.         }
  353.     j = i - 1;
  354.     while(IS_HOR_SPACE(data[j])) data[j--] = '\0';
  355.     data[i++] = '\0';
  356.     while(IS_HOR_SPACE(data[i]) && !IS_END(data[i])) i++;
  357.     if(IS_END(data[i]))
  358.         return(0);
  359.     return(&data[i]);
  360.     }
  361.  
  362.